package cn.cdu.medical.service.impl;

import cn.cdu.medical.entity.MedicalRecord;
import cn.cdu.medical.service.IDoctorWorkbenchService;
import cn.cdu.medical.service.MedicalRecordService;
import cn.cdu.data.entity.User;
import cn.cdu.doctor.entity.UserDoctor;
import cn.cdu.data.service.IUserService;
import cn.cdu.doctor.service.IUserDoctorService;
import cn.cdu.doctor.entity.Doctor;
import cn.cdu.doctor.entity.DoctorScheduling;
import cn.cdu.doctor.entity.HospitalOrder;
import cn.cdu.doctor.service.IDoctorService;
import cn.cdu.doctor.service.IDoctorSchedulingService;
import cn.cdu.doctor.service.IHospitalOrderService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.cdu.doctor.mapper.HospitalOrderMapper;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.scheduling.annotation.Scheduled;
import lombok.extern.slf4j.Slf4j;
import cn.cdu.basics.exception.BusinessException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import java.util.*;
import java.time.LocalDateTime;
import java.time.Duration;
import java.time.ZoneId;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.stream.Collectors;
import java.time.Period;
import javax.annotation.PostConstruct;

import org.springframework.context.ApplicationContext;

/**
 * 医生工作台服务实现类
 */
@Slf4j
@Service
public class DoctorWorkbenchServiceImpl extends ServiceImpl<HospitalOrderMapper, HospitalOrder> implements IDoctorWorkbenchService {

    @Autowired
    private IUserService userService;

    // 使用延迟注入解决循环依赖
    @Autowired
    private ApplicationContext applicationContext;

    private MedicalRecordService medicalRecordService;

    @PostConstruct
    public void init() {
        try {
            this.medicalRecordService = applicationContext.getBean(MedicalRecordService.class);
        } catch (Exception e) {
            log.error("Failed to inject MedicalRecordService", e);
            throw new RuntimeException("Failed to initialize MedicalRecordService", e);
        }
    }

    @Autowired
    private IDoctorService doctorService;

    @Autowired
    private IDoctorSchedulingService doctorSchedulingService;

    @Autowired
    private IHospitalOrderService hospitalOrderService;

    @Autowired
    private IUserDoctorService userDoctorService;

    /**
     * 根据用户ID获取医生ID
     *
     * @throws BusinessException 如果用户不是医生
     */
    private String getDoctorIdByUserId(String userId) {
        log.info("Getting doctor ID for user ID: {}", userId);
        QueryWrapper<UserDoctor> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        UserDoctor userDoctor = userDoctorService.getOne(wrapper);
        if (userDoctor == null) {
            log.warn("No doctor found for user ID: {}", userId);
            throw new BusinessException("您不是医生，无法访问医生工作台。如果您是医生，请联系管理员关联您的医生信息。");
        }
        log.info("Found doctor ID: {} for user ID: {}", userDoctor.getDoctorId(), userId);
        return userDoctor.getDoctorId();
    }

    @Override
    public Map<String, Object> getDoctorInfo(String userId) {
        Map<String, Object> result = new HashMap<>();
        log.info("Getting doctor info for userId: {}", userId);
        
        try {
            // 获取医生ID
            String doctorId = getDoctorIdByUserId(userId);
            log.info("Found doctorId: {} for userId: {}", doctorId, userId);
            
            // 获取医生信息
            Doctor doctor = doctorService.getById(doctorId);
            log.info("Found doctor info: {}", doctor);
            
            if (doctor == null) {
                log.error("No doctor details found for doctorId: {}", doctorId);
                throw new BusinessException("未找到医生详细信息，请联系管理员完善您的医生信息。");
            }
            
            // 获取用户基本信息
            User user = userService.getById(userId);
            log.info("Found user info: {}", user);
            
            if (user == null) {
                log.error("No user found for userId: {}", userId);
                throw new BusinessException("未找到用户信息，请重新登录。");
            }
            
            // 获取今日排班信息
            LocalDate today = LocalDate.now();
            QueryWrapper<DoctorScheduling> schedulingWrapper = new QueryWrapper<>();
            schedulingWrapper.eq("doctor_id", doctorId)
                            .eq("date", today.format(DateTimeFormatter.ISO_LOCAL_DATE));
            List<DoctorScheduling> todaySchedulings = doctorSchedulingService.list(schedulingWrapper);
            log.info("Found today's scheduling: {}", todaySchedulings);
            
            // 组装医生基本信息
            result.put("name", user.getNickname());
            result.put("avatar", user.getAvatar());
            result.put("department", doctor.getSubjectName());
            result.put("title", doctor.getPostLevel());
            
            // 组装排班信息
            Map<String, Object> schedules = new HashMap<>();
            Map<String, Object> morning = new HashMap<>();
            morning.put("label", "上午");
            morning.put("time", "暂无排班");
            
            Map<String, Object> afternoon = new HashMap<>();
            afternoon.put("label", "下午");
            afternoon.put("time", "暂无排班");
            
            // 处理排班信息
            for (DoctorScheduling scheduling : todaySchedulings) {
                log.info("Processing schedule: step={}, number={}", scheduling.getStep(), scheduling.getNumber());
                int number = Integer.parseInt(scheduling.getNumber());
                if (DoctorScheduling.MORNING_SHIFT.equals(scheduling.getStep())) {
                    morning.put("time", number > 0 ? "共" + number + "号" : "暂无排班");
                } else if (DoctorScheduling.AFTERNOON_SHIFT.equals(scheduling.getStep())) {
                    afternoon.put("time", number > 0 ? "共" + number + "号" : "暂无排班");
                }
            }
            
            schedules.put("morning", morning);
            schedules.put("afternoon", afternoon);
            result.put("schedules", schedules);
            
            log.info("Final doctor info result: {}", result);
            
        } catch (BusinessException e) {
            log.error("Business error getting doctor info for userId: {}", userId, e);
            throw e; // 直接抛出业务异常
        } catch (Exception e) {
            log.error("Unexpected error getting doctor info for userId: {}", userId, e);
            throw new BusinessException("获取医生信息时发生错误，请稍后重试或联系管理员。");
        }
        
        return result;
    }

    // 每天凌晨2点清除医生信息缓存
    @Scheduled(cron = "0 0 2 * * ?")
    @CacheEvict(value = "doctorInfo", allEntries = true)
    public void clearDoctorInfoCache() {
        // 清除缓存
    }

    @Override
    public List<Map<String, Object>> getWaitingPatients(String userId) {
        return getPatientsByStatus(userId, 0);
    }

    @Override
    public List<Map<String, Object>> getInProgressPatients(String userId) {
        return getPatientsByStatus(userId, 1);
    }

    @Override
    public List<Map<String, Object>> getCompletedPatients(String userId) {
        return getPatientsByStatus(userId, 2);
    }

    @Override
    public boolean updatePatientStatus(String patientId, String status) {
        HospitalOrder order = hospitalOrderService.getById(patientId);
        if (order != null) {
            // 状态变更为"就诊中"(1)或"已完成"(2)时，关联/创建病历
            int statusValue = Integer.parseInt(status);
            if (statusValue == 1 || statusValue == 2) {
                try {
                    // 确保medicalRecordService已注入
                    if (medicalRecordService != null) {
                        // 获取或创建病历记录
                        MedicalRecord record = medicalRecordService.getOrCreateByOrderId(order.getId());

                        // 如果状态为"已完成"，更新病历状态
                        if (statusValue == 2) {
                            record.setStatus("COMPLETED");
                            medicalRecordService.updateById(record);
                            log.info("Updated medical record status to COMPLETED: {}", record.getId());
                        }
                    } else {
                        log.warn("MedicalRecordService is not available, unable to associate medical record");
                    }
                } catch (Exception e) {
                    log.error("Error associating medical record", e);
                    // 不影响主流程继续执行
                }
            }

            // 更新挂号状态
            order.setStatus(statusValue);
            order.setUpdateTime(new Date());
            boolean result = hospitalOrderService.updateById(order);
            log.info("Updated order status to {}: {}", statusValue, result);
            return result;
        }
        return false;
    }

    @Override
    public List<Map<String, Object>> getPatientHistory(String patientId) {
        log.info("Getting history for patient ID: {}", patientId);
        QueryWrapper<HospitalOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", patientId)
                   .eq("del_flag", 0)
                   .eq("status", 2) // 已完成的就诊记录
                   .orderByDesc("create_time");
        
        List<HospitalOrder> orders = hospitalOrderService.list(queryWrapper);
        log.info("Found {} orders for patient ID: {}", orders.size(), patientId);
        List<Map<String, Object>> history = new ArrayList<>();
        
        for (HospitalOrder order : orders) {
            Map<String, Object> record = new HashMap<>();
            record.put("id", order.getId());
            
            // 获取医生信息
            Doctor doctor = doctorService.getById(order.getDoctorId());
            if (doctor != null) {
                record.put("doctorName", doctor.getDoctorName());
                record.put("department", doctor.getSubjectName());
            } else {
                record.put("doctorName", "未知医生");
                record.put("department", "未知科室");
            }
            
            // 获取病历信息 - 添加空值检查
            if (medicalRecordService != null) {
                try {
                    // 通过orderId查询病历
                    QueryWrapper<MedicalRecord> medicalRecordQuery = new QueryWrapper<>();
                    medicalRecordQuery.eq("order_id", order.getOrderId());
                    MedicalRecord medicalRecord = medicalRecordService.getOne(medicalRecordQuery);

                    if (medicalRecord != null) {
                        record.put("visitDate", medicalRecord.getVisitTime()); // 使用就诊时间
                        record.put("diagnosis", medicalRecord.getDiagnosisName());
                        record.put("treatment", medicalRecord.getInitialDiagnosis());
                        record.put("chiefComplaint", medicalRecord.getChiefComplaint()); // 添加主诉信息
                        record.put("medicalRecordId", medicalRecord.getId()); // 添加病历ID
                        record.put("adviceType", medicalRecord.getAdviceType());
                        record.put("adviceContent", medicalRecord.getAdviceContent());
                    } else {
                        record.put("visitDate", order.getDateTime()); // 如果没有病历记录，使用挂号时间
                        record.put("diagnosis", "无诊断记录");
                        record.put("treatment", "无治疗记录");
                        record.put("chiefComplaint", "无主诉记录");
                        record.put("medicalRecordId", null);
                    }
                } catch (Exception e) {
                    log.error("Error getting medical records for patient: {}", patientId, e);
                    record.put("visitDate", order.getDateTime());
                    record.put("diagnosis", "获取诊断失败");
                    record.put("treatment", "获取治疗记录失败");
                    record.put("chiefComplaint", "获取主诉失败");
                    record.put("medicalRecordId", null);
                }
            } else {
                // MedicalRecordService不可用
                record.put("visitDate", order.getDateTime());
                record.put("diagnosis", "系统维护中");
                record.put("treatment", "系统维护中");
                record.put("chiefComplaint", "系统维护中");
                record.put("medicalRecordId", null);
                log.warn("MedicalRecordService is not available");
            }
            
            history.add(record);
        }
        
        return history;
    }

    @Override
    public Map<String, Object> getPatientList(String doctorId, Integer pageNumber, Integer pageSize, String searchKey) {
        int pageNum = (pageNumber == null) ? 1 : pageNumber;
        int pageSz = (pageSize == null) ? 10 : pageSize;
        return getPatientList(doctorId, pageNum, pageSz, searchKey);
    }

    // int重载实现
    public Map<String, Object> getPatientList(String doctorId, int pageNumber, int pageSize, String searchKey) {
        QueryWrapper<HospitalOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("doctor_id", doctorId).eq("del_flag", 0);
        if (searchKey != null && !searchKey.trim().isEmpty()) {
            queryWrapper.and(qw -> qw.like("user_name", searchKey)
                    .or().like("file_number", searchKey));
        }
        queryWrapper.orderByDesc("create_time");
        // 分页（用MyBatis-Plus的Page）
        IPage<HospitalOrder> page = new Page<>(pageNumber, pageSize);
        IPage<HospitalOrder> resultPage = hospitalOrderService.page(page, queryWrapper);

        // 去重，只保留每个患者最新一条
        Map<String, HospitalOrder> latestPatientMap = new LinkedHashMap<>();
        for (HospitalOrder order : resultPage.getRecords()) {
            latestPatientMap.putIfAbsent(order.getUserId(), order);
        }

        List<Map<String, Object>> records = latestPatientMap.values().stream().map(order -> {
            Map<String, Object> map = new HashMap<>();
            map.put("id", order.getUserId());
            map.put("name", order.getUserName());
            // 可根据需要补充更多字段
            return map;
        }).collect(Collectors.toList());

        Map<String, Object> result = new HashMap<>();
        result.put("records", records);
        result.put("total", resultPage.getTotal());
        return result;
    }

    public List<Map<String, Object>> getPatientsByStatus(String userId, Integer status) {
        log.info("Getting patients for user ID: {} with status: {}", userId, status);

        // 获取医生ID
        QueryWrapper<UserDoctor> doctorWrapper = new QueryWrapper<>();
        doctorWrapper.eq("user_id", userId);
        UserDoctor userDoctor = userDoctorService.getOne(doctorWrapper);

        if (userDoctor == null) {
            log.warn("No doctor found for user ID: {}", userId);
            throw new BusinessException("未找到医生信息，请确认您是否有医生权限");
        }

        String doctorId = userDoctor.getDoctorId();
        log.info("Found doctor ID: {} for user ID: {}", doctorId, userId);

        // 查询该医生的患者
        QueryWrapper<HospitalOrder> orderWrapper = new QueryWrapper<>();
        orderWrapper.eq("doctor_id", doctorId)
                   .eq("status", status)
                   .eq("del_flag", 0)
                   .orderByDesc("date_time"); // 按就诊时间倒序排列

        List<HospitalOrder> orders = hospitalOrderService.list(orderWrapper);
        log.info("Found {} orders for doctor ID: {}", orders.size(), doctorId);

        List<Map<String, Object>> result = new ArrayList<>();

        for (HospitalOrder order : orders) {
            Map<String, Object> patientInfo = new HashMap<>();
            // 基本信息
            patientInfo.put("id", order.getId());
            patientInfo.put("orderId", order.getOrderId());
            patientInfo.put("name", order.getUserName());
            patientInfo.put("status", order.getStatus());
            patientInfo.put("registrationTime", order.getDateTime());
            patientInfo.put("createTime", order.getCreateTime());

            // 获取患者的详细信息
            User patient = userService.getById(order.getUserId());
            if (patient != null) {
                patientInfo.put("phone", patient.getMobile());
                patientInfo.put("gender", patient.getSex());
                patientInfo.put("age", calculateAge(patient.getBirth()));
                patientInfo.put("email", patient.getEmail());
                patientInfo.put("address", patient.getAddress());
                log.info("Added patient info for patient ID: {}", patient.getId());
            } else {
                patientInfo.put("phone", "未知");
                patientInfo.put("gender", "未知");
                patientInfo.put("age", null);
                patientInfo.put("email", "未知");
                patientInfo.put("address", "未知");
                log.warn("No patient info found for ID: {}", order.getUserId());
            }

            // 获取病历信息
            if (medicalRecordService != null) {
                try {
                    QueryWrapper<MedicalRecord> recordWrapper = new QueryWrapper<>();
                    recordWrapper.eq("order_id", order.getOrderId())
                            .orderByDesc("create_time")
                            .last("LIMIT 1");

                    MedicalRecord record = medicalRecordService.getOne(recordWrapper);
                    if (record != null) {
                        patientInfo.put("visitTime", record.getVisitTime());
                        patientInfo.put("diagnosis", record.getDiagnosisName());
                        patientInfo.put("treatment", record.getInitialDiagnosis());
                        patientInfo.put("chiefComplaint", record.getChiefComplaint());
                        patientInfo.put("deptName", record.getDeptName());
                        log.info("Found medical record for order {}: chiefComplaint={}", order.getOrderId(), record.getChiefComplaint());
                    } else {
                        // 如果没有找到病历记录，尝试创建一个新的
                        record = medicalRecordService.getOrCreateByOrderId(order.getOrderId());
                        if (record != null) {
                            patientInfo.put("visitTime", record.getVisitTime());
                            patientInfo.put("diagnosis", record.getDiagnosisName());
                            patientInfo.put("treatment", record.getInitialDiagnosis());
                            patientInfo.put("chiefComplaint", record.getChiefComplaint());
                            patientInfo.put("deptName", record.getDeptName());
                            log.info("Created new medical record for order {}: chiefComplaint={}", order.getOrderId(), record.getChiefComplaint());
                        } else {
                            patientInfo.put("visitTime", order.getDateTime());
                            patientInfo.put("diagnosis", "暂无诊断");
                            patientInfo.put("treatment", "暂无治疗方案");
                            patientInfo.put("chiefComplaint", "暂无主诉");
                            patientInfo.put("deptName", "暂无科室信息");
                            log.info("Failed to create medical record for order {}", order.getOrderId());
                        }
                    }
                } catch (Exception e) {
                    log.error("Error getting medical record for order: {}", order.getId(), e);
                    patientInfo.put("visitTime", order.getDateTime());
                    patientInfo.put("diagnosis", "获取诊断失败");
                    patientInfo.put("treatment", "获取治疗方案失败");
                    patientInfo.put("chiefComplaint", "获取主诉失败");
                    patientInfo.put("deptName", "获取科室信息失败");
                }
            } else {
                patientInfo.put("visitTime", order.getDateTime());
                patientInfo.put("diagnosis", "系统维护中");
                patientInfo.put("treatment", "系统维护中");
                patientInfo.put("chiefComplaint", "系统维护中");
                patientInfo.put("deptName", "系统维护中");
                log.warn("MedicalRecordService is not available");
            }

            result.add(patientInfo);
        }

        log.info("Returning {} patients for doctor ID: {} with status: {}", result.size(), doctorId, status);
        return result;
    }

    private Integer calculateAge(Date birthDate) {
        if (birthDate == null) {
            return null;
        }
        LocalDate birth = birthDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        return Period.between(birth, LocalDate.now()).getYears();
    }

    @Override
    public List<Map<String, Object>> getTodaySchedule(String userId) {
        log.info("Getting today's schedule for userId: {}", userId);
        List<Map<String, Object>> result = new ArrayList<>();

        try {
            // 获取医生ID
            String doctorId = getDoctorIdByUserId(userId);

            // 获取今日排班信息
            LocalDate today = LocalDate.now();
            QueryWrapper<DoctorScheduling> schedulingWrapper = new QueryWrapper<>();
            schedulingWrapper.eq("doctor_id", doctorId)
                           .eq("date", today.format(DateTimeFormatter.ISO_LOCAL_DATE))
                           .orderByAsc("step");  // 按时段排序

            List<DoctorScheduling> todaySchedulings = doctorSchedulingService.list(schedulingWrapper);

            // 转换为前端需要的格式
            for (DoctorScheduling scheduling : todaySchedulings) {
                Map<String, Object> scheduleInfo = new HashMap<>();
                scheduleInfo.put("period", scheduling.getStep());  // 时段（上午/下午）
                int number = Integer.parseInt(scheduling.getNumber());
                scheduleInfo.put("number", number > 0 ? number : "0");  // 就诊编号
                scheduleInfo.put("isBooked", scheduling.getOrderFlag() == 1);  // 是否已预约
                result.add(scheduleInfo);
            }

            log.info("Found {} schedule(s) for doctor ID: {}", result.size(), doctorId);

        } catch (BusinessException e) {
            log.error("Business error getting schedule for userId: {}", userId, e);
            throw e;
        } catch (Exception e) {
            log.error("Unexpected error getting schedule for userId: {}", userId, e);
            throw new BusinessException("获取排班信息时发生错误，请稍后重试。");
        }

        return result;
    }

    @Override
    public List<Map<String, Object>> getDoctorSchedules(String userId, String startDate, String endDate) {
        log.info("Getting doctor schedules for userId: {} from {} to {}", userId, startDate, endDate);

        try {
            // 获取医生ID
            String doctorId = getDoctorIdByUserId(userId);

            // 解析日期
            DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE;
            LocalDate start = LocalDate.parse(startDate.trim(), formatter);
            LocalDate end = LocalDate.parse(endDate.trim(), formatter);

            // 查询排班信息
            QueryWrapper<DoctorScheduling> schedulingWrapper = new QueryWrapper<>();
            schedulingWrapper.eq("doctor_id", doctorId)
                           .ge("date", start.format(formatter))
                           .le("date", end.format(formatter))
                           .orderByAsc("date", "step");

            List<DoctorScheduling> schedules = doctorSchedulingService.list(schedulingWrapper);
            log.info("Found {} schedule records", schedules.size());

            // 按日期分组处理排班信息
            Map<String, Map<String, Integer>> schedulesMap = new HashMap<>();
            for (DoctorScheduling schedule : schedules) {
                String date = schedule.getDate();
                schedulesMap.putIfAbsent(date, new HashMap<>());

                Map<String, Integer> daySchedule = schedulesMap.get(date);
                if (DoctorScheduling.MORNING_SHIFT.equals(schedule.getStep())) {
                    daySchedule.put("morningNumber", Integer.parseInt(schedule.getNumber()));
                } else if (DoctorScheduling.AFTERNOON_SHIFT.equals(schedule.getStep())) {
                    daySchedule.put("afternoonNumber", Integer.parseInt(schedule.getNumber()));
                }
            }

            // 转换为前端需要的格式
            List<Map<String, Object>> result = new ArrayList<>();
            LocalDate current = start;
            while (!current.isAfter(end)) {
                String currentDate = current.format(formatter);
                Map<String, Object> daySchedule = new HashMap<>();
                daySchedule.put("date", currentDate);

                Map<String, Integer> numbers = schedulesMap.getOrDefault(currentDate, new HashMap<>());
                int morningNumber = numbers.getOrDefault("morningNumber", 0);
                int afternoonNumber = numbers.getOrDefault("afternoonNumber", 0);

                daySchedule.put("morningNumber", morningNumber > 0 ? morningNumber : "0");
                daySchedule.put("afternoonNumber", afternoonNumber > 0 ? afternoonNumber : "0");

                result.add(daySchedule);
                current = current.plusDays(1);
            }

            log.info("Returning {} days of schedules", result.size());
            return result;

        } catch (BusinessException e) {
            log.error("Business error getting doctor schedules", e);
            throw e;
        } catch (Exception e) {
            log.error("Error getting doctor schedules", e);
            throw new BusinessException("获取排班信息时发生错误：" + e.getMessage());
        }
    }
} 